#ifndef PNG_CHUNCKS_HPP
#define PNG_CHUNCKS_HPP

/** This namespace contains everything related to the PNG file format.
  @see http://www.w3.org/TR/2003/REC-PNG-20031110/
*/
namespace png {
// We need a portable way to define the size of chunck parts.
#ifdef WIN32
  typedef unsigned int u4bytes; ///< Unsigned 4 bytes
#endif

#define MAKE_U4BYTES(a, b, c, d) ( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d))

  /** These are the first 8 bytes always found in the beginning of a PNG file
    @see 5.2 in http://www.w3.org/TR/2003/REC-PNG-20031110/
  */
  unsigned char const signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
  
  // These macros are used to access the first 2 fields of every chunck.
  #define PNG_CHUNCK_LENGTH(c) static_cast<png::u4bytes>(MAKE_U4BYTES((c)[0], (c)[1], (c)[2], (c)[3]))
  #define PNG_CHUNCK_NAME(c) (c + 4)

  // These macros are used to access the IHDR chunck fields.
  // Note that these start at the data field of the chunck NOT at its length or name.
  // see: 11.2.2 in http://www.w3.org/TR/2003/REC-PNG-20031110/
  #define PNG_IHDR_WIDTH(c) static_cast<png::u4bytes>(MAKE_U4BYTES((c)[0], (c)[1], (c)[2], (c)[3]))
  #define PNG_IHDR_HEIGHT(c) static_cast<png::u4bytes>(MAKE_U4BYTES((c)[4], (c)[5], (c)[6], (c)[7]))
  #define PNG_IHDR_BIT_DEPTH(c) static_cast<signed short>((c)[8])
  #define PNG_IHDR_COLOR_TYPE(c) static_cast<signed short>((c)[9])
  #define PNG_IHDR_COMPRESSION_METHOD(c) static_cast<short>((c)[10])
  #define PNG_IHDR_FILTER_METHOD(c) static_cast<short>((c)[11])
  #define PNG_IHDR_INTERLACE_METHOD(c) static_cast<short>((c)[12])
  
  
  /** These are the possible values of color type in the IHDR_COLOR_TYPE field.
    @see Table 11.1 in http://www.w3.org/TR/2003/REC-PNG-20031110/
  */
  enum color_type {
    CT_GREYSCALE = 0,
    CT_TRUECOLOR = 2,
    CT_INDEXED_COLOR = 3,
    CT_GREYSCALE_WITH_ALPHA = 4,
    CT_TRUECOLOR_WITH_ALPHA = 6,
  };

  enum compression_method {
    /// This is the only compression method currently defined by the standard and it is always to be used.
    CM_DEFLATE_INFLATE = 0
  };
  
  enum filter_method {
    /// This is the only filter method currently defined by the standard and it is always to be used.
    FM_ADAPTIVE = 0
  };
  
  enum interlace_method {
    /// No Interlace
    IM_NONE = 0,
    /// Adam7 Interlace
    IM_ADAM7 = 1
  };
  
  // These macros are used to access the PLTE chunck fields.
  // Note that these start at the data field of the chunck NOT at its length or name.
  // see: 11.2.3 in http://www.w3.org/TR/2003/REC-PNG-20031110/
  #define PNG_PLTE_RED(c) static_cast<unsigned short>((c)[0])
  #define PNG_PLTE_GREEN(c) static_cast<unsigned short>((c)[1])
  #define PNG_PLTE_BLUE(c) static_cast<unsigned short>((c)[2])
}

#endif
